package basics.arrays;

import java.util.Arrays;

/**
 * Java 数组常见问题与解决方案
 * 
 * 本类展示了使用数组时常见的问题和解决方法
 */
public class ArrayProblemsAndSolutions {
    
    public static void main(String[] args) {
        System.out.println("===== Java 数组常见问题与解决方案 =====");
        
        // 数组越界问题
        arrayIndexOutOfBounds();
        
        // 数组扩容问题
        arrayResizing();
        
        // 数组空指针问题
        arrayNullPointer();
        
        // 数组性能问题
        arrayPerformance();
        
        // 多线程数组问题
        arrayConcurrencyIssues();
    }
    
    /**
     * 数组越界问题及解决方案
     */
    private static void arrayIndexOutOfBounds() {
        System.out.println("\n----- 数组越界问题 -----");
        
        int[] numbers = {1, 2, 3, 4, 5};
        
        // 问题：访问超出数组范围的索引
        try {
            int value = numbers[5]; // 这会抛出 ArrayIndexOutOfBoundsException
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("捕获到数组越界异常: " + e.getMessage());
        }
        
        // 解决方案1：在访问前检查索引
        int index = 5;
        if (index >= 0 && index < numbers.length) {
            int value = numbers[index];
            System.out.println("安全访问数组元素: " + value);
        } else {
            System.out.println("索引 " + index + " 超出数组范围");
        }
        
        // 解决方案2：使用工具类方法，避免直接索引访问
        // 例如使用 Arrays.binarySearch() 查找元素
    }
    
    /**
     * 数组扩容问题及解决方案
     */
    private static void arrayResizing() {
        System.out.println("\n----- 数组扩容问题 -----");
        
        // 问题：数组大小固定，无法动态增长
        int[] original = {1, 2, 3};
        System.out.println("原始数组: " + Arrays.toString(original));
        
        // 解决方案1：创建新数组并复制
        int[] expanded = new int[original.length * 2];
        System.arraycopy(original, 0, expanded, 0, original.length);
        System.out.println("扩容后的数组: " + Arrays.toString(expanded));
        
        // 解决方案2：使用 Arrays.copyOf
        int[] expanded2 = Arrays.copyOf(original, original.length * 2);
        System.out.println("使用copyOf扩容: " + Arrays.toString(expanded2));
        
        // 解决方案3：使用ArrayList替代固定大小数组
        System.out.println("更好的解决方案：使用ArrayList代替固定大小数组");
    }
    
    /**
     * 数组空指针问题及解决方案
     */
    private static void arrayNullPointer() {
        System.out.println("\n----- 数组空指针问题 -----");
        
        // 问题：未初始化的数组引用
        String[] names = null;
        
        // 这会导致 NullPointerException
        try {
            int length = names.length;
        } catch (NullPointerException e) {
            System.out.println("捕获到空指针异常: " + e.getMessage());
        }
        
        // 解决方案：在使用数组前检查是否为null
        if (names != null) {
            int length = names.length;
            System.out.println("数组长度: " + length);
        } else {
            System.out.println("数组为null，需要先初始化");
            names = new String[0]; // 初始化为空数组而不是null
        }
        
        // 引用类型数组的元素也可能为null
        String[] cities = new String[3];
        cities[0] = "北京";
        // cities[1]和cities[2]为null
        
        // 安全地遍历数组，避免空指针异常
        for (String city : cities) {
            if (city != null) {
                System.out.println("城市: " + city.toUpperCase());
            } else {
                System.out.println("城市: 未指定");
            }
        }
    }
    
    /**
     * 数组性能问题及优化方案
     */
    private static void arrayPerformance() {
        System.out.println("\n----- 数组性能问题 -----");
        
        // 问题1：频繁创建和销毁大型数组
        System.out.println("问题：频繁创建和销毁大型数组会导致垃圾回收压力");
        
        // 解决方案：使用数组池或缓存重用数组
        System.out.println("解决方案：使用数组池或对象池重用数组");
        
        // 问题2：不当的数组遍历方式
        int[] largeArray = new int[1000];
        Arrays.fill(largeArray, 1);
        
        // 低效的遍历方式（对于大型多维数组）
        int[][] matrix = new int[100][100];
        
        long start = System.nanoTime();
        // 按列遍历二维数组（不符合内存布局）
        for (int col = 0; col < 100; col++) {
            for (int row = 0; row < 100; row++) {
                matrix[row][col] = 1;
            }
        }
        long end = System.nanoTime();
        System.out.println("按列遍历耗时: " + (end - start) / 1000000.0 + " 毫秒");
        
        start = System.nanoTime();
        // 按行遍历二维数组（符合内存布局，更高效）
        for (int row = 0; row < 100; row++) {
            for (int col = 0; col < 100; col++) {
                matrix[row][col] = 1;
            }
        }
        end = System.nanoTime();
        System.out.println("按行遍历耗时: " + (end - start) / 1000000.0 + " 毫秒");
    }
    
    /**
     * 多线程环境下的数组问题及解决方案
     */
    private static void arrayConcurrencyIssues() {
        System.out.println("\n----- 多线程数组问题 -----");
        
        // 问题：多线程同时访问和修改数组
        System.out.println("问题：数组不是线程安全的，多线程并发修改可能导致数据不一致");
        
        // 解决方案1：使用同步块
        System.out.println("解决方案1：使用synchronized同步访问");
        final int[] sharedArray = new int[10];
        
        // 示例代码（实际使用时）:
        /*
        synchronized (sharedArray) {
            sharedArray[0] = 100;
        }
        */
        
        // 解决方案2：使用线程安全的集合类
        System.out.println("解决方案2：使用CopyOnWriteArrayList等线程安全集合");
        
        // 解决方案3：使用原子类
        System.out.println("解决方案3：使用AtomicIntegerArray等原子数组类");
        
        // 解决方案4：使用不可变数组
        System.out.println("解决方案4：使用不可变数组，每次操作返回新数组");
    }
} 